package com.lanzhou.yuanfen.security.session;

import com.lanzhou.yuanfen.security.MyUserDetails;
import com.lanzhou.yuanfen.security.SocialDetails;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.HashMap;

/**
 * @ClassName: {@link GlobalSessionContext}
 * @Description: 全局Session容器
 * @author: Lanzhou
 * @date: 2020/5/28 19:17
 * @QQ: 1627518680
 * @Copyright:2020 All rights reserved.
 */
@Slf4j
@Component
public class GlobalSessionContext {

    /**
     * 用户id与与会话之间映射
     */
    private final HashMap<Object, HttpSession> sessionMap = new HashMap<>();

    /**
     * 会话注册器
     */
    @Resource
    private EnhanceSessionRegistryImpl enhanceSessionRegistryImpl;

    synchronized void add(HttpSession session) {
        if (session != null) {
            SessionInformation sessionInformation = enhanceSessionRegistryImpl.getSessionInformation(session.getId());
            if (sessionInformation != null) {
                Object principal = sessionInformation.getPrincipal();
                if (principal != null) {
                    if (principal instanceof UserDetails) {
                        // 狗日其它用户的通通下线:
                        enhanceSessionRegistryImpl.invalidateSession((UserDetails) principal, sessionInformation.getSessionId());
                    }
                    // 当是表单登入和社交已绑定账户的时候
                    if (principal instanceof MyUserDetails) {
                        sessionMap.put(((MyUserDetails) principal).getUser().getUserKey(), session);
                    }
                    // 当是社交(首次)登入的时候
                    if (principal instanceof SocialDetails) {
                        sessionMap.put(((SocialDetails) principal).getSocialKey(), session);
                    }
                    log.info("添加session成功, 当前session个数为: {} 个", sessionMap.size());
                }
            }
        }
    }

    synchronized void delete(HttpSession session) {
        if (session != null) {
            SessionInformation sessionInformation = enhanceSessionRegistryImpl.getSessionInformation(session.getId());
            if (sessionInformation != null) {
                MyUserDetails user = (MyUserDetails) sessionInformation.getPrincipal();
                if (user != null && user.isLogout()) {
                    // 恢复标记使真正退出时可以被删除
                    user.setLogout(true);
                    sessionMap.remove(user.getUser().getUserKey());
                    log.info("删除session成功, 当前session个数为: {} 个", sessionMap.size());
                }
            }
        }
    }

    /**
     * 主要就是靠这个获取当前用户ID对应的会话的HttpSession, 然后有Session就可以操作当前Session的SecurityContext了嘿嘿
     *
     * @param id
     * @return
     */
    public HttpSession getSessionByUserId(Long id) {
        return sessionMap.get(id);
    }


}
